package com.qkun.library.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.text.TextUtils;

import androidx.annotation.RawRes;
import androidx.core.util.Pair;

import com.qkun.library.base.BaseApplication;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import static android.content.Context.MODE_APPEND;
import static android.content.Context.MODE_PRIVATE;
import static com.qkun.library.utils.TextUtilsEx.ENTER;

/**
 * @author qinkun
 * @date 6/16 0016 22:05
 * @description 判断文件是否存在或者文件是否是文件、是否是文件夹等，File类本身就是具有api的，所以不需要多做封装
 *
 * <p>
 * //获取文件最后修改的时间戳（毫秒）
 * {@link File#lastModified()}
 * //获取文件长度，可以通过{@link StorageUtils#formatStorageSize(long)}将该长度转化为大小
 * {@link File#length()}
 * //是否是隐藏文件
 * {@link File#isHidden()}
 * ......
 * <code>
 * //读取Resource内的文件
 * getClassLoader().getResourceAsStream("xxx.xml");
 * </code>
 * </p>
 */
public final class FileUtils {

    private FileUtils() {
    }

    public static File makeDir(File dir) {
        if (Utils.nonNull(dir)) {
            if ((dir.exists() && dir.isDirectory()) || dir.mkdirs()) {
                return dir;
            }
        }
        return null;
    }

    public static File makeDir(String dirPath) {
        return TextUtils.isEmpty(dirPath) ? null : makeDir(new File(dirPath));
    }

    public static File makeDir(File parent, String child) {
        return TextUtils.isEmpty(child) ? null : makeDir(new File(parent, child));
    }

    public static boolean checkFile(File file) {
        return Utils.nonNull(file) && file.exists() && file.isFile();
    }

    /**
     * 创建文件，当文件不存在并且创建失败的时候返回null
     *
     * @param file
     * @return
     */
    public static File makeFile(File file) {
        if (Utils.nonNull(file)) {
            if (file.exists() && file.isFile()) {
                return file;
            } else if (Utils.nonNull(makeDir(file.getParentFile()))) {
                try {
                    if (file.createNewFile()) return file;
                } catch (IOException e) {
                    MyLog.e(e);
                }
            }
        }
        return null;
    }

    public static File makeFile(String filePath) {
        return TextUtils.isEmpty(filePath) ? null : makeFile(new File(filePath));
    }

    public static File makeFile(File parent, String child) {
        return TextUtils.isEmpty(child) ? null : makeFile(new File(parent, child));
    }

    /**
     * 删除旧的文件并创建新的文件
     *
     * @param file
     * @return
     */
    public static File makeNewFile(File file) {
        if (Utils.nonNull(file)) {
            if (file.exists() && file.isFile()) {
                if (file.delete()) {
                    try {
                        if (file.createNewFile()) return file;
                    } catch (IOException e) {
                        MyLog.e(e);
                    }
                }
            } else if (Utils.nonNull(makeDir(file.getParentFile()))) {
                try {
                    if (file.createNewFile()) return file;
                } catch (IOException e) {
                    MyLog.e(e);
                }
            }
        }
        return null;
    }

    /**
     * 删除旧的文件夹并创建新的文件夹
     *
     * @param dir
     * @return
     */
    public static File makeNewDir(File dir) {
        if (Utils.nonNull(dir)) {
            if ((dir.exists() && dir.isDirectory())) {
                if (deleteDir(dir) && dir.mkdirs()) {
                    return dir;
                }
            } else if (dir.mkdirs()) {
                return dir;
            }
        }
        return null;
    }

    /**
     * 重命名文件
     *
     * @param file
     * @param newName
     * @return
     */
    public static boolean rename(File file, String newName) {
        if (Utils.nonNull(file)
                && file.exists()
                && !TextUtils.isEmpty(newName)
                && !newName.equals(file.getName())) {
            File newFile = new File(file.getParent() + File.separator + newName);
            return !newFile.exists() && file.renameTo(newFile);
        }
        return false;
    }

    public static boolean rename(String filePath, String newName) {
        return !TextUtils.isEmpty(filePath) && rename(new File(filePath), newName);
    }

    /**
     * 清空目录
     *
     * @param dir
     * @return
     */
    public static boolean clearDir(File dir) {
        if (Utils.nonNull(dir)) {
            if (dir.exists() && dir.isDirectory()) {
                File[] files = dir.listFiles();
                if (!ArraysEx.isEmpty(files)) {
                    for (File file : files) {
                        if (file.isFile()) {
                            if (!file.delete()) return false;
                        } else if (file.isDirectory()) {
                            if (!deleteDir(file)) return false;
                        }
                    }
                }
                return true;
            }
        }
        return false;
    }

    public static boolean clearDir(String dirPath) {
        return clearDir(new File(dirPath));
    }


    /**
     * 删除目录
     *
     * @param dir
     * @return
     */
    public static boolean deleteDir(File dir) {
        return clearDir(dir) && dir.delete();
    }

    public static boolean deleteDir(String dirPath) {
        return deleteDir(new File(dirPath));
    }

    /**
     * 删除文件
     *
     * @param file
     * @return
     */
    public static boolean deleteFile(File file) {
        return checkFile(file) && file.delete();
    }

    public static boolean deleteFile(final String filePath) {
        return deleteFile(new File(filePath));
    }


    /**
     * 删除文件或目录
     *
     * @param f
     * @return
     */
    public static boolean delete(File f) {
        if (Utils.nonNull(f) && f.exists()) {
            if (f.isFile()) {
                return deleteFile(f);
            } else {
                return deleteDir(f);
            }
        }
        return false;
    }

    public static boolean delete(String path) {
        return delete(new File(path));
    }

    /**
     * 复制文件/文件夹 若要进行文件夹复制，请勿将目标文件夹置于源文件夹中
     *
     * @param source
     * @param target
     */
    public static void copy(File source, String target) {
        if (Utils.nonNull(source) && source.exists()) {
            if (source.isFile()) {
                File newFile = makeNewFile(new File(target));
                if (Utils.nonNull(newFile)) {
                    InputStream inputStream = null;
                    FileOutputStream outputStream = null;
                    try {
                        inputStream = new FileInputStream(source);
                        outputStream = new FileOutputStream(newFile);
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = inputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, len);
                        }
                    } catch (FileNotFoundException e) {
                        MyLog.e(e);
                    } catch (IOException e) {
                        MyLog.e(e);
                    } finally {
                        try {
                            if (Utils.nonNull(inputStream)) inputStream.close();
                            if (Utils.nonNull(outputStream)) outputStream.close();
                        } catch (IOException e) {
                            MyLog.e(e);
                        }
                    }
                }
            } else {
                File newDir = makeDir(new File(target));
                if (Utils.nonNull(newDir)) {
                    File[] files = source.listFiles();
                    if (!ArraysEx.isEmpty(files)) {
                        if (!target.endsWith(File.separator)) {
                            target += File.separator;
                        }
                        for (File file : files) {
                            copy(file, target + file.getName());
                        }
                    }
                }
            }
        }
    }

    /**
     * 判断文件后缀名是否是指定的后缀名
     *
     * @param file
     * @param suffix
     * @return
     */
    public static boolean equalSuffix(File file, String suffix) {
        if (checkFile(file)
                && Utils.nonNull(suffix)
                && (suffix.length() > 1)
                && suffix.startsWith(".")) {
            return file.getName().toUpperCase().endsWith(suffix.toUpperCase());
        }
        return false;
    }

    /**
     * 获取目录下的列表（不获取二级子目录下的）
     *
     * @param dir
     * @return
     */
    public static List<File> getChildren(File dir) {
        if (Utils.nonNull(dir) && dir.exists() && dir.isDirectory()) {
            return Arrays.asList(dir.listFiles());
        }
        return null;
    }

    public static List<File> getChildren(String dirPath) {
        return TextUtils.isEmpty(dirPath) ? null : getChildren(new File(dirPath));
    }

    /**
     * 获取目录下的所有文件符合后缀名的文件
     *
     * @param dir
     * @param fileList
     * @param includeSubChildrenFiles
     * @param suffixes
     */
    public static void filterChildrenFiles(File dir, List<File> fileList, boolean includeSubChildrenFiles, String... suffixes) {
        if (Utils.isNull(fileList)) fileList = new ArrayList<>();
        List<File> files = getChildren(dir);
        if (!Utils.isEmpty(files)) {
            final int N = files.size();
            final boolean E = ArraysEx.isEmpty(suffixes);
            for (int i = 0; i < N; i++) {
                File file = files.get(i);
                if (file.isFile()) {
                    if (E) {
                        fileList.add(file);
                    } else {
                        for (String suffix : suffixes) {
                            if (equalSuffix(file, suffix)) {
                                fileList.add(file);
                                break;
                            }
                        }
                    }
                } else if (includeSubChildrenFiles) {
                    filterChildrenFiles(file, fileList, true);
                }
            }
        }
    }

    public static void filterChildrenFiles(String dirPath, List<File> fileList, boolean includeSubChildrenFiles, String... suffixes) {
        if (!TextUtils.isEmpty(dirPath)) {
            filterChildrenFiles(new File(dirPath), fileList, includeSubChildrenFiles, suffixes);
        }
    }

    /**
     * 获取目录下所有符合filter的文件
     *
     * @param dir
     * @param fileList
     * @param includeSubChildrenFiles
     * @param filter
     */
    public static void filterChildrenFiles(File dir, List<File> fileList, boolean includeSubChildrenFiles, FilenameFilter filter) {
        if (Utils.isNull(fileList)) fileList = new ArrayList<>();
        List<File> files = getChildren(dir);
        if (!Utils.isEmpty(files)) {
            final int N = files.size();
            for (int i = 0; i < N; i++) {
                File file = files.get(i);
                if (file.isFile()) {
                    if (filter.accept(file.getParentFile(), file.getName())) {
                        fileList.add(file);
                    }
                } else if (includeSubChildrenFiles) {
                    filterChildrenFiles(file, fileList, true, filter);
                }
            }
        }
    }

    public static void filterChildrenFiles(String dirPath, List<File> fileList, boolean includeSubChildrenFiles, FilenameFilter filter) {
        if (!TextUtils.isEmpty(dirPath)) {
            filterChildrenFiles(new File(dirPath), fileList, includeSubChildrenFiles, filter);
        }
    }

    /**
     * 获取目录下和指定文件名相同的文件
     * <p>忽略大小写</p>
     *
     * @param dir
     * @param fileList
     * @param includeSubChildrenFiles
     * @param fileName
     * @param ignoreCase
     */
    public static void searchFile(File dir, List<File> fileList, boolean includeSubChildrenFiles, String fileName, boolean ignoreCase) {
        if (Utils.isNull(fileList)) fileList = new ArrayList<>();
        List<File> files = getChildren(dir);
        if (!Utils.isEmpty(files)) {
            final int N = files.size();
            for (int i = 0; i < N; i++) {
                File file = files.get(i);
                if (file.isFile()) {
                    if (ignoreCase) {
                        if (file.getName().toUpperCase().equals(fileName.toUpperCase())) {
                            fileList.add(file);
                        }
                    } else if (file.getName().equals(fileName)) {
                        fileList.add(file);
                    }
                } else if (includeSubChildrenFiles) {
                    searchFile(file, fileList, true, fileName, ignoreCase);
                }
            }
        }
    }

    public static void searchFile(String dirPath, List<File> fileList, boolean includeSubChildrenFiles, String fileName, boolean ignoreCase) {
        searchFile(new File(dirPath), fileList, includeSubChildrenFiles, fileName, ignoreCase);
    }

    /**
     * 简单的获取文件编码格式
     *
     * @param file
     * @return
     */
    public static String getFileCodingSimple(File file) {
        if (checkFile(file)) {
            InputStream inputStream = null;
            try {
                inputStream = new BufferedInputStream(new FileInputStream(file));
                final int CODING = (inputStream.read() << 8) + inputStream.read();
                switch (CODING) {
                    case 0xefbb:
                        return "UTF-8";
                    case 0xfffe:
                        return "Unicode";
                    case 0xfeff:
                        return "UTF-16BE";
                    default:
                        return "GBK";
                }
            } catch (IOException e) {
                MyLog.e(e);
            } finally {
                if (Utils.nonNull(inputStream)) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        MyLog.e(e);
                    }
                }
            }
        }
        return "";
    }

    public static String getFileCodingSimple(String filePath) {
        return getFileCodingSimple(new File(filePath));
    }

    /**
     * 获取文件行数
     * <p>比readLine要快很多</p>
     *
     * @param file
     * @return
     */
    public static int getFileLines(final File file) {
        if (checkFile(file)) {
            InputStream inputStream = null;
            try {
                inputStream = new BufferedInputStream(new FileInputStream(file));
                final byte[] buffer = new byte[1024];
                int len;
                int count = 1;
                if (Utils.nonNull(ENTER) && ENTER.endsWith("\n")) {
                    while ((len = inputStream.read(buffer, 0, 1024)) != -1) {
                        for (int i = 0; i < len; ++i) {
                            if (buffer[i] == '\n') ++count;
                        }
                    }
                } else {
                    while ((len = inputStream.read(buffer, 0, 1024)) != -1) {
                        for (int i = 0; i < len; ++i) {
                            if (buffer[i] == '\r') ++count;
                        }
                    }
                }
                return count;
            } catch (IOException e) {
                MyLog.e(e);
            } finally {
                if (Utils.nonNull(inputStream)) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        MyLog.e(e);
                    }
                }
            }
        }
        return 0;
    }

    public static int getFileLines(final String filePath) {
        return getFileLines(new File(filePath));
    }

    /**
     * 获取目录长度
     *
     * @param f
     * @return
     */
    public static long getLength(File f) {
        if (Utils.nonNull(f) && f.exists()) {
            if (f.isFile()) return f.length();
            long len = 0;
            List<File> fileList = new ArrayList<>();
            //后面就不需要再次判断是否存在以及是否是文件了
            filterChildrenFiles(f, fileList, true);
            if (!Utils.isEmpty(fileList)) {
                final int N = fileList.size();
                for (int i = 0; i < N; i++) {
                    len += fileList.get(i).length();
                }
            }
            return len;
        }
        return -1;
    }

    public static long getLength(String path) {
        return getLength(new File(path));
    }

    /**
     * 获取大小
     *
     * @param f
     * @return
     */
    public static String getSize(File f) {
        long len = getLength(f);
        Pair<String, String> stringPair = StorageUtils.formatStorageSize(len);
        return stringPair.first + stringPair.second;
    }

    public static String getSize(String path) {
        return getSize(new File(path));
    }

    /**
     * 获取文件的MD5校验码
     *
     * @param file
     * @return
     */
    public static byte[] getFileMD5(File file) {
        if (Utils.nonNull(file)) {
            DigestInputStream digestInputStream = null;
            try {
                MessageDigest messageDigest = MessageDigest.getInstance("MD5");
                digestInputStream = new DigestInputStream(new FileInputStream(file), messageDigest);
                byte[] buffer = new byte[1024 * 256];
                while (true) {
                    if (digestInputStream.read(buffer) <= 0) break;
                }
                messageDigest = digestInputStream.getMessageDigest();
                return messageDigest.digest();
            } catch (NoSuchAlgorithmException | IOException e) {
                MyLog.e(e);
            } finally {
                if (Utils.nonNull(digestInputStream)) {
                    try {
                        digestInputStream.close();
                    } catch (IOException e) {
                        MyLog.e(e);
                    }
                }
            }
        }
        return null;
    }

    public static byte[] getFileMD5(String filePath) {
        return getFileMD5(new File(filePath));
    }

    /**
     * byteArray转hexString
     * <p>
     * bytes2HexString(new byte[] { 0, (byte) 0xa8 }) returns 00A8
     * </p>
     *
     * @param bytes 字节数组
     * @return 16进制大写字符串
     */
    private static String bytes2HexString(byte[] bytes) {
        if (Utils.nonNull(bytes)) {
            final int L = bytes.length;
            if (L > 0) {
                final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
                char[] ret = new char[L << 1];
                for (int i = 0, j = 0; i < L; i++) {
                    ret[j++] = HEX_DIGITS[bytes[i] >>> 4 & 0x0f];
                    ret[j++] = HEX_DIGITS[bytes[i] & 0x0f];
                }
                return new String(ret);
            }
        }
        return null;
    }

    public static String getFileMD5ToString(File file) {
        return bytes2HexString(getFileMD5(file));
    }

    public static String getFileMD5ToString(final String filePath) {
        return bytes2HexString(getFileMD5(filePath));
    }

    /**
     * 获取全路径中的文件名
     *
     * @param filePath
     * @param haveExtension 是否带拓展名
     * @return
     */
    public static String getFileName(String filePath, boolean haveExtension) {
        if (!TextUtils.isEmpty(filePath)) {
            int lastSep = filePath.lastIndexOf(File.separator);
            String fileName;
            if (haveExtension) {
                fileName = lastSep == -1 ? filePath : filePath.substring(lastSep + 1);
            } else {
                int lastPoi = filePath.lastIndexOf('.');
                if (lastSep == -1) {
                    fileName = (lastPoi == -1 ? filePath : filePath.substring(0, lastPoi));
                } else if (lastPoi == -1 || lastSep > lastPoi) {
                    fileName = filePath.substring(lastSep + 1);
                } else {
                    fileName = filePath.substring(lastSep + 1, lastPoi);
                }
            }
            if (checkFileName(fileName)) {
                return fileName;
            }
        }
        return "";
    }

    public static String getFileName(File file, boolean haveExtension) {
        if (checkFile(file)) {
            return getFileName(file.getPath(), haveExtension);
        }
        return null;
    }

    /**
     * 获取全路径中的文件拓展名
     *
     * @param filePath
     * @return
     */
    public static String getFileExtension(String filePath) {
        if (!TextUtils.isEmpty(filePath)) {
            int lastPoi = filePath.lastIndexOf('.');
            int lastSep = filePath.lastIndexOf(File.separator);
            if (lastPoi > -1 && lastSep < lastPoi) {
                return filePath.substring(lastPoi + 1);
            }
        }
        return filePath;
    }

    public static String getFileExtension(File file) {
        return checkFile(file) ? getFileExtension(file.getPath()) : null;
    }

    public static boolean checkFileName(String fileName) {
        if (TextUtils.isEmpty(fileName) || fileName.length() > 255) {
            return false;
        } else {
            String regex = "[^\\s\\\\/:*?\"<>|](\\x20|[^\\s\\\\/:*?\"<>|])*[^\\s\\\\/:*?\"<>|.]$";
            return fileName.matches(regex);
        }
    }

    /**
     * 写内部文件
     * 不适合用来保存一些复杂的数据
     * 文件的存储路径：/data/data/应用程序包名/files/
     *
     * @param fileName 仅仅是名称而已，不包含路径
     * @param content
     * @param append
     * @return
     */
    public static boolean writeInternalFile(String fileName, String content, boolean append) {
        fileName = getFileName(fileName, true);
        if (!TextUtils.isEmpty(fileName)) {
            BufferedWriter bufferedWriter = null;
            try {
                FileOutputStream fileOutputStream = BaseApplication.getAppContext()
                        .openFileOutput(fileName, append ? MODE_APPEND : MODE_PRIVATE);
                bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream));
                bufferedWriter.write(content);
                return true;
            } catch (FileNotFoundException e) {
                MyLog.e(e);
            } catch (IOException e) {
                MyLog.e(e);
            } finally {
                if (Utils.nonNull(bufferedWriter)) {
                    try {
                        bufferedWriter.close();
                    } catch (IOException e) {
                        MyLog.e(e);
                    }
                }
            }
        }
        return false;
    }

    /**
     * 读内部文件
     * 文件路径：/data/data/应用程序包名/files/
     *
     * @param fileName
     * @return
     */
    public static String readInternalFile(String fileName) {
        BufferedReader bufferedReader = null;
        try {
            FileInputStream fileInputStream = BaseApplication.getAppContext().openFileInput(fileName);
            bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
            StringBuilder builder = new StringBuilder();
            String line;
            while (Utils.nonNull((line = bufferedReader.readLine()))) {
                builder.append(line);
            }
            return builder.toString();
        } catch (IOException e) {
            MyLog.e(e);
        } finally {
            if (Utils.nonNull(bufferedReader)) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    MyLog.e(e);
                }
            }
        }
        return null;
    }

    public static boolean writeFile(File file, String content, boolean append) {
        if (Utils.nonNull(file)) {
            BufferedWriter bufferedWriter = null;
            try {
                bufferedWriter = new BufferedWriter(new FileWriter(file, append));
                bufferedWriter.write(content);
                return true;
            } catch (IOException e) {
                MyLog.e(e);
            } finally {
                if (Utils.nonNull(bufferedWriter)) {
                    try {
                        bufferedWriter.close();
                    } catch (IOException e) {
                        MyLog.e(e);
                    }
                }
            }
        }
        return false;
    }

    public static String readFile(File file) {
        if (checkFile(file)) {
            BufferedReader bufferedReader = null;
            try {
                bufferedReader = new BufferedReader(new FileReader(file));
                StringBuilder builder = new StringBuilder();
                String line;
                while (Utils.nonNull((line = bufferedReader.readLine()))) {
                    builder.append(line);
                }
                return builder.toString();
            } catch (IOException e) {
                MyLog.e(e);
            } finally {
                if (Utils.nonNull(bufferedReader)) {
                    try {
                        bufferedReader.close();
                    } catch (IOException e) {
                        MyLog.e(e);
                    }
                }
            }
        }
        return null;
    }

    /**
     * 写压缩文件
     *
     * @param file
     * @param content
     */
    public static void writeCompressedFile(File file, String content) {
        if (!TextUtils.isEmpty(content)) {
            InputStream inputStream = null;
            GZIPOutputStream outputStream = null;
            try {
                inputStream = new ByteArrayInputStream(content.getBytes());
                outputStream = new GZIPOutputStream(new FileOutputStream(file));
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
            } catch (IOException e) {
                MyLog.e(e);
            } finally {
                try {
                    if (Utils.nonNull(outputStream)) {
                        outputStream.close();
                    }
                    if (Utils.nonNull(inputStream)) {
                        inputStream.close();
                    }
                } catch (IOException e) {
                    MyLog.e(e);
                }
            }
        }
    }

    /**
     * 读取压缩文件
     *
     * @param file
     * @return
     */
    public static String readCompressedFile(File file) {
        if (checkFile(file)) {
            GZIPInputStream inputStream = null;
            ByteArrayOutputStream outputStream = null;
            try {
                inputStream = new GZIPInputStream(new FileInputStream(file));
                outputStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
                return new String(outputStream.toByteArray());
            } catch (IOException e) {
                MyLog.e(e);
            } finally {
                try {
                    if (Utils.nonNull(outputStream)) {
                        outputStream.close();
                    }
                    if (Utils.nonNull(inputStream)) {
                        inputStream.close();
                    }
                } catch (IOException e) {
                    MyLog.e(e);
                }
            }
        }
        return null;
    }

    /**
     * 读取Assert中的文件
     *
     * @param fileName
     * @return
     */
    public static String readAssertFile(String fileName) {
        if (checkFileName(fileName)) {
            BufferedReader bufferedReader = null;
            try {
                InputStream inputStream = BaseApplication.getAppContext().getResources().getAssets().open(fileName);
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder builder = new StringBuilder();
                String line;
                while (Utils.nonNull((line = bufferedReader.readLine()))) {
                    builder.append(line);
                }
                return builder.toString();
            } catch (IOException e) {
                MyLog.e(e);
            } finally {
                if (Utils.nonNull(bufferedReader)) {
                    try {
                        bufferedReader.close();
                    } catch (IOException e) {
                        MyLog.e(e);
                    }
                }
            }
        }
        return null;
    }

    /**
     * 读取Assert中的图片
     *
     * @param imageName
     * @return
     */
    public static Bitmap readAssertImage(String imageName) {
        if (checkFileName(imageName)) {
            InputStream inputStream = null;
            try {
                inputStream = BaseApplication.getAppContext().getResources().getAssets().open(imageName);
                return BitmapFactory.decodeStream(inputStream);
            } catch (IOException e) {
                MyLog.e(e);
            } finally {
                if (Utils.nonNull(inputStream)) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        MyLog.e(e);
                    }
                }
            }
        }
        return null;
    }

    /**
     * 获取Assert中子文件夹（可以是多级）下的文件名
     *
     * @param path
     * @return
     */
    public static String[] getAssertFileNamesAtPath(String path) {
        if (!TextUtils.isEmpty(path)) {
            try {
                return BaseApplication.getAppContext().getResources().getAssets().list(path);
            } catch (IOException e) {
                MyLog.e(e);
            }
        }
        return null;
    }

    /**
     * 读取Raw中的文件
     *
     * @param resId
     */
    public static String readRawFile(@RawRes int resId) {
        BufferedReader bufferedReader = null;
        try {
            InputStream inputStream = BaseApplication.getAppContext().getResources().openRawResource(resId);
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder builder = new StringBuilder();
            String line;
            while (Utils.nonNull((line = bufferedReader.readLine()))) {
                builder.append(line);
            }
            return builder.toString();
        } catch (IOException e) {
            MyLog.e(e);
        } finally {
            if (Utils.nonNull(bufferedReader)) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    MyLog.e(e);
                }
            }
        }
        return null;
    }

    public static String readSdCardFile(String filepath) {
        if (!TextUtils.isEmpty(filepath)) {
            File file = new File(Environment.getExternalStorageDirectory(), filepath);
            if (checkFile(file)) {
                return readFile(file);
            }
        }
        return null;
    }

    public static boolean writeSdCardFile(String filepath, String content, boolean isAppend) {
        return writeFile(makeFile(Environment.getExternalStorageDirectory(), filepath), content, isAppend);
    }

    /**
     * 保存网络文件
     *
     * @param filepath
     * @param spec     网络文件的路径
     * @return
     */
    public static boolean saveNetworkFile(String filepath, String spec) {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(makeFile(filepath));
            inputStream = new URL(spec).openStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            return true;
        } catch (IOException e) {
            MyLog.e(e);
        } finally {
            try {
                if (Utils.nonNull(inputStream)) {
                    inputStream.close();
                }
                if (Utils.nonNull(outputStream)) {
                    outputStream.close();
                }
            } catch (IOException e) {
                MyLog.e(e);
            }
        }
        return false;
    }

}
